﻿using System.Collections.Generic;
using NUnit.Framework;
using SharePoint.Orm.TestHelpers;

namespace SharePoint.Orm.Caml {
	[TestFixture]
	public class CamlQueryTest : TestBase {
		[Test]
		public void TestOrderBy_NoItems() {
			CamlQuery query = new CamlQuery();
			string found = query.ToString(true);
			XmlAssert.AreEqual("<Query />", found);
		}

		[Test]
		public void TestOrderBy() {
			CamlQuery query = new CamlQuery();
			query.AddOrderBy(new CamlFieldRef("field1"));
			query.AddOrderBy(new CamlFieldRef("field2"));
			string found = query.ToString(true);
			XmlAssert.AreEqual(@"
<Query>
  <OrderBy>
    <FieldRef Name='field1' />
    <FieldRef Name='field2' />
  </OrderBy>
</Query>", found);
		}

		[Test]
		public void TestConstructorSyntax() {
			CamlQuery query = new CamlQuery {
				GroupBy = new CamlGroupBy {
					Collapse = true,
					GroupLimit = 100,
					First = new CamlFieldRef("groupby_field1"),
					Second = new CamlFieldRef("groupby_field2")
				},
				OrderBy = new CamlOrderBy {
					Fields = new List<CamlFieldRef> {
  		         		new CamlFieldRef("orderby_field1"),
						new CamlFieldRef("orderby_field2")
  		         	}
				},
				Where = new CamlWhere {
					Root = new CamlAnd {
						First = new CamlEquals {
							FieldRef = new CamlFieldRef("eq_field1"),
							Value = new CamlValue(CamlValueType.String, "val1")
						},
						Second = new CamlBeginsWith {
							FieldRef = new CamlFieldRef("beginswith_field1"),
							Value = new CamlValue(CamlValueType.String, "val2")
						}
					}
				}
			};
			string found = query.ToString(true);
			XmlAssert.AreEqual(@"
<Query>
  <GroupBy Collapse='TRUE' GroupLimit='100'>
    <FieldRef Name='groupby_field1' />
    <FieldRef Name='groupby_field2' />
  </GroupBy>
  <OrderBy>
    <FieldRef Name='orderby_field1' />
    <FieldRef Name='orderby_field2' />
  </OrderBy>
  <Where>
    <And>
      <Eq>
        <FieldRef Name='eq_field1' />
        <Value Type='String'>val1</Value>
      </Eq>
      <BeginsWith>
        <FieldRef Name='beginswith_field1' />
        <Value Type='String'>val2</Value>
      </BeginsWith>
    </And>
  </Where>
</Query>", found);
		}

		[Test]
		public void TestParse_EmptyString() {
			const string str = @"";
			CamlQuery query = CamlQuery.Parse(str);
			Assert.IsNotNull(query);
			Assert.IsNull(query.OrderBy);
			Assert.IsNull(query.Where);
			Assert.IsNull(query.GroupBy);
		}

		[Test]
		public void TestParse_Null() {
			CamlQuery query = CamlQuery.Parse(null);
			Assert.IsNotNull(query);
			Assert.IsNull(query.OrderBy);
			Assert.IsNull(query.Where);
			Assert.IsNull(query.GroupBy);
		}

		[Test]
		public void TestParse_Simple() {
			CamlQuery query = CamlQuery.Parse("<Query/>");
			Assert.IsNotNull(query);
			Assert.IsNull(query.OrderBy);
			Assert.IsNull(query.Where);
			Assert.IsNull(query.GroupBy);
		}

		[Test]
		public void TestParse_NoWrappingQuery() {
			const string str = @"<OrderBy><FieldRef Name='orderby_field1' /></OrderBy>";
			CamlQuery query = CamlQuery.Parse(str);
			Assert.IsNotNull(query);

			Assert.IsNotNull(query.OrderBy);
			Assert.AreEqual(1, query.OrderBy.Fields.Count);
			Assert.AreEqual("orderby_field1", query.OrderBy.Fields[0].FieldName);

			Assert.IsNull(query.Where);
			Assert.IsNull(query.GroupBy);
		}

		[Test]
		public void TestParse_Complex() {
			const string str = @"<Query>
  <GroupBy Collapse='TRUE' GroupLimit='100'>
    <FieldRef Name='groupby_field1' />
    <FieldRef Name='groupby_field2' Ascending='FALSE' />
  </GroupBy>
  <OrderBy>
    <FieldRef Name='orderby_field1' />
    <FieldRef Name='orderby_field2' />
  </OrderBy>
  <Where>
    <And>
      <Eq>
        <FieldRef Name='eq_field1' />
        <Value Type='string'>val1</Value>
      </Eq>
      <BeginsWith>
        <FieldRef Name='beginswith_field1' />
        <Value Type='string'>val2</Value>
      </BeginsWith>
    </And>
  </Where>
</Query>";
			CamlQuery query = CamlQuery.Parse(str);
			Assert.IsNotNull(query);
			Assert.IsNotNull(query.GroupBy);
			Assert.AreEqual(true, query.GroupBy.Collapse);
			Assert.AreEqual(100, query.GroupBy.GroupLimit);
			Assert.AreEqual("groupby_field1", query.GroupBy.First.FieldName);
			Assert.AreEqual("groupby_field2", query.GroupBy.Second.FieldName);
			Assert.AreEqual(false, query.GroupBy.Second.Ascending);

			Assert.IsNotNull(query.OrderBy);
			Assert.AreEqual(2, query.OrderBy.Fields.Count);
			Assert.AreEqual("orderby_field1", query.OrderBy.Fields[0].FieldName);
			Assert.AreEqual("orderby_field2", query.OrderBy.Fields[1].FieldName);

			Assert.IsNotNull(query.Where);
			Assert.IsNotNull(query.Where.Root);
			CamlLogicalOp root = query.Where.Root as CamlLogicalOp;
			Assert.IsNotNull(root);
			Assert.IsNotNull(root.First);
			CamlComparisonOp eq = root.First as CamlComparisonOp;
			Assert.IsNotNull(eq);
			Assert.AreEqual("eq_field1", eq.FieldRef.FieldName);
			Assert.AreEqual("val1", eq.Value.Value);
			Assert.IsNotNull(root.Second);
			CamlComparisonOp beginsWith = root.Second as CamlComparisonOp;
			Assert.IsNotNull(beginsWith);
			Assert.AreEqual("beginswith_field1", beginsWith.FieldRef.FieldName);
			Assert.AreEqual("val2", beginsWith.Value.Value);
		}

		[Test]
		public void TestCamlValue_CamlCurrentUser() {
			CamlQuery query = new CamlQuery {
				Where = new CamlWhere {
					Root = new CamlEquals {
						FieldRef = new CamlFieldRef("eq_field1"),
						Value = new CamlValue {
							Type = CamlValueType.Integer,
							ValueChild = new CamlCurrentUser()
						}
					}
				}
			};
			string found = query.ToString(false);
			XmlAssert.AreEqual(@"
<Where>
  <Eq>
    <FieldRef Name='eq_field1' />
    <Value Type='Integer'>
      <UserID Type=""Integer"" />
    </Value>
  </Eq>
</Where>", found);
		}
		
		[Test]
		public void TestCamlValue_CamlGroupMember() {
			CamlQuery query = new CamlQuery {
				Where = new CamlWhere {
					Root = new CamlCurrentUserGroupMember(
						new CamlFieldRef("eq_field1")
					)
				}
			};
			string found = query.ToString(false);
			XmlAssert.AreEqual(@"
<Where>
  <Membership Type=""CurrentUserGroups"">
    <FieldRef Name='eq_field1' />
  </Membership>
</Where>", found);
		}
	}
}
